#include "nixie_driver.h"
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "hr_sc04_driver.h"

void nixie_driver_config(void)
{
    // 外设时钟使能
    rcu_periph_clock_enable(DI_RCU);
    rcu_periph_clock_enable(SCK_RCU);
    rcu_periph_clock_enable(RCK_RCU);

    // 输出模式:3个引脚都是推挽输出,
    gpio_mode_set(DI_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_OTYPE_PP, DI_GPIO_PIN);
    gpio_mode_set(SCK_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_OTYPE_PP, SCK_GPIO_PIN);
    gpio_mode_set(RCK_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_OTYPE_PP, RCK_GPIO_PIN);
    gpio_output_options_set(DI_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, DI_GPIO_PIN);
    gpio_output_options_set(SCK_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SCK_GPIO_PIN);
    gpio_output_options_set(RCK_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RCK_GPIO_PIN);
    // RCK,SCK默认低电平;
    gpio_bit_reset(RCK_GPIO_PORT, RCK_GPIO_PIN);
    gpio_bit_reset(SCK_GPIO_PORT, SCK_GPIO_PIN);
}

/**
 * 移位寄存器
 */
void nixie_driver_shift_clk(void)
{
    // SCK拉高电平
    //  延时1um;
    //  SCK恢复低电平;
    gpio_bit_write(SCK_GPIO_PORT, SCK_GPIO_PIN, 1);
    delay_1us(1);
    gpio_bit_write(SCK_GPIO_PORT, SCK_GPIO_PIN, 0);
}

/**
 * 锁存
 */
void nixie_driver_lock_clk(void)
{
    // RCK上升沿
    // NIXIE_DELAY() 稍等一会儿
    // RCK(0) 确保下一次拉高有上升沿
    gpio_bit_write(RCK_GPIO_PORT, RCK_GPIO_PIN, 1);
    delay_1us(1);
    gpio_bit_write(RCK_GPIO_PORT, RCK_GPIO_PIN, 0);
}

void nixie_driver_send_1_bit(uint8_t bit)
{
    // DI 引脚写入数据
    gpio_bit_write(DI_GPIO_PORT, DI_GPIO_PIN, bit == 0 ? 0 : 1);
    // 移位寄存器
    nixie_driver_shift_clk();
}

void nixie_driver_send_16_bit(uint16_t data)
{
    // 从右往左,依次发送
    for (int i = 15; i >= 0; i--)
    {
        nixie_driver_send_1_bit((data >> i) & 0x1U);
    }
}

void nixie_driver_send_data(uint16_t data)
{
    // 发送完整的16bit数据，拆成16个1bit发送，
    // 最后锁存即可
    // printf("nixie_driver_send_data:%#x\n", data);
    nixie_driver_send_16_bit(data);
    nixie_driver_lock_clk();
}

uint16_t nixie_driver_cover_to_data32(uint8_t num, FlagStatus dp, uint8_t dip)
{
    uint16_t data = dp ? 0b0000000000000000 : 0b1000000000000000;
    // // 小数点
    // if (dp)
    // {
    //     // 小数点不亮
    //     data = 0b0111111100000000;
    // }
    // else
    // {
    //     // 亮
    //     data = 0b1111111100000000;
    // }

    // 数字

    switch (num)
    {
    case 0:
        data |= NIXIE_LED_GONGYANG_0 << 8;
        break;
    case 1:
        data |= NIXIE_LED_GONGYANG_1 << 8;
        break;
    case 2:
        data |= NIXIE_LED_GONGYANG_2 << 8;
        break;
    case 3:
        data |= NIXIE_LED_GONGYANG_3 << 8;
        break;
    case 4:
        data |= NIXIE_LED_GONGYANG_4 << 8;
        break;
    case 5:
        data |= NIXIE_LED_GONGYANG_5 << 8;
        break;
    case 6:
        data |= NIXIE_LED_GONGYANG_6 << 8;
        break;
    case 7:
        data |= NIXIE_LED_GONGYANG_7 << 8;
        break;
    case 8:
        data |= NIXIE_LED_GONGYANG_8 << 8;
        break;
    case 9:
        data |= NIXIE_LED_GONGYANG_9 << 8;
        break;
    default:
        break;
    }

    // printf("after num , %#x\n", data);
    switch (dip)
    {
    case 0:
        data |= NIXIE_DIP_GONGYANG_0;
        break;
    case 1:
        data |= NIXIE_DIP_GONGYANG_1;
        break;
    case 2:
        data |= NIXIE_DIP_GONGYANG_2;
        break;
    case 3:
        data |= NIXIE_DIP_GONGYANG_3;
        break;
    case 4:
        data |= NIXIE_DIP_GONGYANG_4;
        break;
    case 5:
        data |= NIXIE_DIP_GONGYANG_5;
        break;
    case 6:
        data |= NIXIE_DIP_GONGYANG_6;
        break;
    case 7:
        data |= NIXIE_DIP_GONGYANG_7;
        break;
    }

    // printf("after dip , %#x\n", data);
    return data;
}

/**
 * 拼装16位数字,发送给硬件
 */
void nixie_driver_display_single(uint8_t num, FlagStatus dp, uint8_t dip)
{
    uint16_t data = nixie_driver_cover_to_data32(num, dp, dip);
    nixie_driver_send_data(data);
}

// static uint8_t *current_display_num;
// static int current_display_num_len;
// static FlagStatus *current_display_dps;

/**
 * 8个数字
 */
void nixie_driver_display(uint8_t *num, int len, FlagStatus *dps)
{
    //printf("len = %d\n", len);
    //    current_display_num = num;
    //    current_display_num_len = len;
    //    current_display_dps = dps;
    //
    uint8_t i;
    for (i = 0; i < len; i++)
    {
//        if (*(num + i) == 0 && *(dps + i) == 0)
//        {
//            continue;
//        }
        nixie_driver_display_single(*(num + i), *(dps + i), i);
        // delay_1ms(10);
    }
}

void nixie_driver_delay(uint32_t us)
{
    // int count = us / NIXIE_DELAY_DURATION;
    // while (count--)
    // {
    //     uint8_t i;
    //     for (i = 0; i < current_display_num_len; i++)
    //     {
    //         nixie_driver_display_single(*(current_display_num + i), *(current_display_dps + i), i);
    //         // delay_1ms(10);
    //     }
    // }
}

void nixie_driver_test(void)
{
    // uint8_t num[9] = {0};
    float distance = hr_sc04_driver_get_distance_mine();
    // snprintf(num, sizeof(num), "%08d\n", (int)distance);

    uint8_t num[8] = {1, 2, 3, 4, 5, 6, 7, 8};

    FlagStatus dps[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    nixie_driver_display(num, sizeof(num) / sizeof(uint8_t), dps);

    // nixie_driver_display_single(6, 1, 5);
}
